package com.kaifamiao.thread.d0927;

import java.time.LocalDateTime;
import java.util.concurrent.locks.ReentrantLock;

/*
    线程安全：  多线程、同一个资源进行修改
    同步、锁
        锁： Lock lock = new ReentrantLock()
        同步： 同步的块，锁是谁？ 可以是 自定义对象、this、class对象。锁是同一个

 */
public class Demo {

    public static void main(String[] args) {
        Cook cook = new Cook();

        Thread t1 = new WaitRunnable("wait1", cook);
        Thread t2 = new WaitRunnable("wait2", cook);
        Thread t3 = new WaitRunnable("wait3", cook);

        Thread n1 = new NotifyRunnable(cook);

        t1.start();
        t2.start();
        t3.start();
        n1.start();
    }
}

class Cook{

    private String name;

    public synchronized void cook(){
//        notify(); // 唤醒一个(wait)线程
//        notifyAll(); // 唤醒所有(wait)线程

        if (name != null){
            try {
                wait(); // 等待面包被消费
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
//        name = LocalDateTime.now().toString(); // 做了一个面包
//        System.out.println("做了一个面包： " + name);
//        notifyAll(); // 唤醒所有消费者
    }

    public synchronized void eat(){
        if (name == null){
            System.out.println(Thread.currentThread().getName() + " 等待");
            try {
                wait(100); // 释放锁
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println(Thread.currentThread().getName() + " 消费了一个面包 " + name);
            name = null; // 消费了面包
//            notify(); // 唤醒 cook 线程
        }
    }
}

class WaitRunnable extends Thread{

    private Cook cook;

    public WaitRunnable(String s, Cook cook) {
        super(s);
        this.cook = cook;
    }

    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            cook.eat();
        }
    }
}

class NotifyRunnable extends Thread{
    private Cook cook;

    public NotifyRunnable(Cook cook){
        this.cook = cook;
    }

    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            cook.cook();
        }

    }
}
